package com.yiyuan.app.service.impl;

import com.alibaba.fastjson.JSON;
import com.yiyuan.app.dao.DOrderRechargeDAO;
import com.yiyuan.app.dao.TradeRecordAlipayDetailDAO;
import com.yiyuan.app.dao.TradeRecordWxpayDetailDAO;
import com.yiyuan.app.entity.enums.OrderStatusEnum;
import com.yiyuan.app.entity.po.DOrderRechargePO;
import com.yiyuan.app.entity.po.TradeRecordAlipayDetailPO;
import com.yiyuan.app.entity.po.TradeRecordWxpayDetailPO;
import com.yiyuan.app.service.BaseDealPayService;
import com.yiyuan.app.service.PayNotifyService;
import com.wechat.pay.java.service.partnerpayments.app.model.Transaction;
import com.wechat.pay.java.service.refund.model.*;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Objects;

@Slf4j
@Service
@AllArgsConstructor
public class PayNotifyServiceImpl implements PayNotifyService {

    private final DOrderRechargeDAO dOrderRechargeDAO;
    private final TradeRecordAlipayDetailDAO tradeRecordAlipayDetailDAO;
    private final TradeRecordWxpayDetailDAO tradeRecordWxpayDetailDAO;
    private final BaseDealPayService baseDealPayService;

    @Override
    @Transactional
    public boolean wxPayNotify(Transaction transaction) throws Exception {
        DOrderRechargePO rechargePO = dOrderRechargeDAO.findByOrderNumberLock(transaction.getOutTradeNo());
        if (Objects.isNull(rechargePO)) {
            return Boolean.FALSE;
        }
        if (OrderStatusEnum.pay_ready.getCode().equals(rechargePO.getStatus())) {
            rechargePO.setOutTradeNo(transaction.getTransactionId());
            if (transaction.getTradeState().equals(Transaction.TradeStateEnum.SUCCESS)) {
                rechargePO.setStatus(OrderStatusEnum.pay_success.getCode());
                rechargePO.setPayAmount(BigDecimal.valueOf(transaction.getAmount().getPayerTotal()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_UP));
                DateTimeFormatter formatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
                LocalDateTime dateTime = LocalDateTime.parse(transaction.getSuccessTime(), formatter);
                rechargePO.setPayTime(dateTime);
            } else {
                rechargePO.setStatus(OrderStatusEnum.pay_fail.getCode());
            }
            dOrderRechargeDAO.updateById(rechargePO);
            TradeRecordWxpayDetailPO po = new TradeRecordWxpayDetailPO();
            po.setAppId(transaction.getSpAppid());
            po.setMchId(transaction.getSpMchid());
            po.setTransactionId(transaction.getTransactionId());
            po.setOutTradeNo(transaction.getOutTradeNo());
            po.setTradeType(transaction.getTradeType().name());
            po.setTradeState(transaction.getTradeState().name());
            po.setBankType(transaction.getBankType());
            po.setAttach(transaction.getAttach());
            po.setSuccessTime(transaction.getSuccessTime());
            po.setPayer(JSON.toJSONString(transaction.getPayer()));
            po.setAmount(JSON.toJSONString(transaction.getAmount()));
            po.setPromotionDetail(JSON.toJSONString(transaction.getPromotionDetail()));
            tradeRecordWxpayDetailDAO.save(po);
            baseDealPayService.dealOrder(rechargePO);
        }
        return Boolean.TRUE;
    }

    @Override
    public boolean wxRefundNotify(RefundNotification transaction) {
        DOrderRechargePO rechargePO = dOrderRechargeDAO.findByRefundOrderNumberLock(transaction.getOutRefundNo());
        if (Objects.isNull(rechargePO)) {
            return Boolean.FALSE;
        }
        if (OrderStatusEnum.refunding.getCode().equals(rechargePO.getStatus())) {
            if (transaction.getRefundStatus().equals(Status.SUCCESS)
                    || transaction.getRefundStatus().equals(Status.CLOSED)) {
                rechargePO.setStatus(OrderStatusEnum.refund_success.getCode());
            } else {
                rechargePO.setStatus(OrderStatusEnum.refund_fail.getCode());
                rechargePO.setRefundFailReason("退款异常");
            }
            dOrderRechargeDAO.updateById(rechargePO);
        }
        return Boolean.TRUE;
    }

    @Override
    public boolean aliPayNotify(TradeRecordAlipayDetailPO transaction) throws Exception {
        DOrderRechargePO rechargePO = dOrderRechargeDAO.findByOrderNumberLock(transaction.getOutTradeNo());
        if (Objects.isNull(rechargePO)) {
            return Boolean.FALSE;
        }
        if (OrderStatusEnum.pay_ready.getCode().equals(rechargePO.getStatus())) {
            rechargePO.setOutTradeNo(transaction.getTradeNo());
            if (transaction.getTradeStatus().equals("TRADE_SUCCESS")
                    || transaction.getTradeStatus().equals("TRADE_FINISHED")) {
                rechargePO.setStatus(OrderStatusEnum.pay_success.getCode());
                rechargePO.setPayAmount(transaction.getBuyerPayAmount());
                rechargePO.setPayTime(transaction.getGmtPayment());
            } else {
                rechargePO.setStatus(OrderStatusEnum.pay_fail.getCode());
            }
            dOrderRechargeDAO.updateById(rechargePO);
            tradeRecordAlipayDetailDAO.save(transaction);
            baseDealPayService.dealOrder(rechargePO);
        }
        return Boolean.TRUE;
    }
}
